package io.noties.markwon.app.sample;

import com.noties.markwon.annotation.NonNull;

import io.noties.markwon.sample.annotations.MarkwonArtifact;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import ohos.utils.Parcel;
import ohos.utils.Sequenceable;

/**
 * @author: yangrui
 * @function: Sample entry
 * @date: 2021/3/23
 */
public class Sample implements Sequenceable {
    @NonNull
    private String javaClassName;
    @NonNull
    private String id;
    @NonNull
    private String title;
    @NonNull
    private String description;
    @NonNull
    private List<MarkwonArtifact> artifacts;
    @NonNull
    private List<String> tags;

    public Sample(@NonNull String javaClassName, @NonNull String id, @NonNull String title, @NonNull String description, @NonNull List<MarkwonArtifact> artifacts, @NonNull List<String> tags) {
        super();
        this.javaClassName = javaClassName;
        this.id = id;
        this.title = title;
        this.description = description;
        this.artifacts = artifacts;
        this.tags = tags;
    }

    public String getJavaClassName() {
        return javaClassName;
    }

    public String getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public String getDescription() {
        return description;
    }

    public List<MarkwonArtifact> getArtifacts() {
        return artifacts == null ? new ArrayList<>() : artifacts;
    }

    public List<String> getTags() {
        return tags == null ? new ArrayList<>() : tags;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Sample sample = (Sample) o;
        return Objects.equals(javaClassName, sample.javaClassName) &&
                Objects.equals(id, sample.id) &&
                Objects.equals(title, sample.title) &&
                Objects.equals(description, sample.description) &&
                Objects.equals(artifacts, sample.artifacts) &&
                Objects.equals(tags, sample.tags);
    }

    @Override
    public int hashCode() {
        return Objects.hash(javaClassName, id, title, description, artifacts, tags);
    }

    @Override
    public String toString() {
        return "Sample{" +
                "javaClassName='" + javaClassName + '\'' +
                ", id='" + id + '\'' +
                ", title='" + title + '\'' +
                ", description='" + description + '\'' +
                ", artifacts=" + artifacts +
                ", tags=" + tags +
                '}';
    }

    @Override
    public boolean marshalling(Parcel out) {
        if (!out.writeString(this.javaClassName)) {
            return false;
        }
        if (!out.writeString(this.id)) {
            return false;
        }
        if (!out.writeString(this.title)) {
            return false;
        }
        if (!out.writeString(this.description)) {
            return false;
        }
        if (!out.writeInt(this.artifacts.size())) {
            return false;
        }

        for (MarkwonArtifact artifact : this.artifacts) {
            if (!out.writeString(artifact.name())) {
                return false;
            }
        }

        return out.writeStringList(this.tags);
    }

    @Override
    public boolean unmarshalling(Parcel in) {
        String javaClassName = in.readString();
        String id = in.readString();
        String title = in.readString();
        String description = in.readString();
        int size = in.readInt();
        ArrayList<MarkwonArtifact> artifacts = new ArrayList<>(size);

        int i = 0;
        while (i < size) {
            artifacts.add(Enum.valueOf(MarkwonArtifact.class, in.readString()));
            i++;
        }
        List<String> tags = in.readStringList();

        this.javaClassName = javaClassName;
        this.id = id;
        this.title = title;
        this.description = description;
        this.artifacts = artifacts;
        this.tags = tags;
        return true;
    }

    public enum Language {
        /**
         *Language type
         */
        JAVA,
        KOTLIN;
    }

    public static final class Code {
        @NonNull
        final Sample.Language language;
        @NonNull
        private final String sourceCode;

        public Code(@NonNull Sample.Language language, @NonNull String sourceCode) {
            super();
            this.language = language;
            this.sourceCode = sourceCode;
        }

        public Language getLanguage() {
            return language;
        }

        public String getSourceCode() {
            return sourceCode;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Code code = (Code) o;
            return language == code.language &&
                    Objects.equals(sourceCode, code.sourceCode);
        }

        @Override
        public int hashCode() {
            return Objects.hash(language, sourceCode);
        }

        @Override
        public String toString() {
            return "Code{" +
                    "language=" + language +
                    ", sourceCode='" + sourceCode + '\'' +
                    '}';
        }
    }

}
